//create MiniMessage
var fourKgadget_msg = new gadgets.MiniMessage(),
// Get userprefs
fourKgadget_prefs = new gadgets.Prefs(), weekDays = new Array(), months = new Array(), isValidationPassed = false, statusMessage = null, today = new Date(), ACTIVE_EXPENSE = 0,
fourKgadgetGA = new _IG_GA("UA-10296791-2");
// returns envelope begin date
var fourKgadget_getEnvelopeBegin = function() {
	var d = today.getDate(), m = today.getMonth() + 1, oneDay=1000*60*60*24;
	//resolve date according to day of a week
	if(today.getDay()>0){
		d = d-(today.getDay()-1);
	} else {
		d = (d - 6);
	}
	if(d<=0){
		var tmpDate = new Date(today.getTime()-(oneDay*today.getDate()));
		d = tmpDate.getDate();
		m = tmpDate.getMonth()+1;
	}
	if (d < 10) {
		d = '0' + d;
	}
	if (m < 10) {
		m = '0' + m;
	}
	return today.getFullYear() + '-' + m + '-' + d;
};
var weekBeginDate = fourKgadget_getEnvelopeBegin();
// define base URL
var envelopeUrl = fourKgadget_prefs.getString('baseUrl'), dailyExpenseUrl = fourKgadget_prefs
		.getString('baseUrl');
// application starter
var fourKgadget_startApplication = function() {
	// change noCacheId 
	fourKgadget_prefs.set('noCacheId', today.getTime());
	// create date related data
	weekDays = weekDaysStr.split(',');
	months = monthsStr.split(',');
	// validate credentials
	fourKgadget_doValidateCredentials();
	if (isValidationPassed) {
		// request application data
		fourKgadget_envelopeDataLoader();
	}
	fourKgadget_trackUsage("Envelope");
};

var fourKgadget_trackUsage = function(action){
	// track to GA
	var userName = fourKgadget_prefs.getString("login");
	if(!userName || userName==""){
		userName = "anonymus";
	}
	fourKgadgetGA.reportEvent("4kgadget", action, userName);
};

// application data loading function
var fourKgadget_envelopeDataLoader = function() {
	document.getElementById('4kgadget_content').style.display='block';
	var localEnvelopeUrl = envelopeUrl + fourKgadget_prefs.getString('login')
			+ fourKgadget_prefs.getString('envelopeUrl') + weekBeginDate + '?'
			+ today.getTime();
	// request application data
	fourKgadget_RequestHandler(localEnvelopeUrl, fourKgadget_prefs
			.getMsg('envelopeLoading'), fourKgadget_handleEvelopeResponse);
};
// envelope response handler
var fourKgadget_handleEvelopeResponse = function(obj) {
	var isLoaded = false, errorMessage;
	if (obj.data) {
		var persons = obj.data.getElementsByTagName("person");
		isLoaded = persons.length > 0;
	}
	//check whether authentication issue
	if (!isLoaded) {
		var errorDom = obj.data.getElementsByTagName("h2");
		if (errorDom) {
			for ( var h2 = 0; h2 < errorDom.length; h2++) {
				var error = errorDom[h2].firstChild.nodeValue?errorDom[h2].firstChild.nodeValue:'';
				if (error.indexOf('401')) {
					errorMessage = fourKgadget_prefs.getMsg('error401');
					break;
				}
			}
		}
	}
	//process after load
	if (isLoaded) {
		fourKgadget_generateEnvelope(obj.data);
		// recalculate gadget height
		gadgets.window.adjustHeight();
		// hide loading message
		fourKgadget_msg.dismissMessage(statusMessage);
	} else {
		fourKgadget_msg.dismissMessage(statusMessage);
		if (errorMessage == undefined) {
			errorMessage = fourKgadget_prefs.getMsg('envelopeNotLoaded');
		}
		statusMessage = fourKgadget_msg
				.createStaticMessage("<span class='errMessage'>"
						+ errorMessage
						+ "</span>");
	}
};
// parse given envelope date and create human readable string
var fourKgadget_createEnvelopeDate = function(date) {
	var result = date;
	if (date) {
		var d, m, y, expDate = new Date(), _date = date.split('-');
		d = _date[2];
		y = _date[0];
		m = _date[1];
		expDate.setFullYear(y, (m - 1), (d-1));
		result = weekDays[expDate.getDay()] + ", " + d + " "
				+ months[expDate.getMonth()];
		if (today.getDate() == d) {
			result = "<strong style='font-size:9pt;'>" + result + "</strong>";
		} else {
			result = "<span style='font-size:9pt;'>" + result + "</span>";
		}
	}
	return result;
};
//main object
var FourKGadget = function(){
	this.currency = "grn",
	/**
	 * The reference to Preference object.
	 */
	this.prefs = fourKgadget_prefs,
	this.msg = fourKgadget_msg,
	this.baseUrl = '',
	this.executionUrl = '',
	this.dailyExpenseUrl
	this.mode = '',//Test
	this.statusMessage = '',
	/**
	 * Retrieve envelope size information.
	 * @param dom the XML response
	 */
	this.getEnvelopeSize = function(dom){
		var envelopeSize = 0;
		if (dom) {
			var envelopeList = dom.getElementsByTagName('envelope');
			if (envelopeList && envelopeList[0]) {
				envelopeList = envelopeList[0];
				envelopeSize = envelopeList.getAttribute("size");
			}
		}
		return this._getEnvelopeSizeHtml(envelopeSize);
	},
	this._getEnvelopeSizeHtml = function(envelopeSize){
		return '<span class="envelopeSize">'+this.prefs.getMsg('envelopeSize')+": <strong>"+envelopeSize+"</strong>"+" "+this.currency+"</span>";
	},
	/**
	 * Retrieve account data.
	 */
	this._retriveAccountData = function(){
		var thisCopy = this,
			testMode = this.mode!=''?'/'+this.mode:'';
		this.requestHandler(this.baseUrl+this.prefs.getString('login')+testMode, null, function(resObj){
			if (resObj && resObj.data) {
				var currency = resObj.data.getElementsByTagName("currency");
				if (currency && currency[0]) {
					currency = currency[0];
					thisCopy.currency = currency.firstChild.nodeValue;
				}
			}
		});
	},
	/**
	 * AJAX request performer.
	 */
	this.requestHandler = function(url, message, callback, method) {
		// request application data
		var params = {}, headers = {};
		if (method == undefined) {
			method = gadgets.io.MethodType.GET;
		}
		params[gadgets.io.RequestParameters.METHOD] = method;
		params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
		headers['4KAuth'] = this.prefs.getString('password');
		headers['4KApplication'] = this.prefs.getString('apiKey');
		params[gadgets.io.RequestParameters.HEADERS] = headers;
		if (callback == undefined) {
			callback = function() {
			};
		}
		gadgets.io.makeRequest(url, callback, params);
		if (message) {
			this.statusMessage = this.createStaticMsg(message);
		}
	},
	this.dismissMessage = function(msg){
		this.msg.dismissMessage(msg);
	},
	this.createStaticMsg = function(message){
		this.msg.createStaticMessage("<span class='message'>" + message + "</span>");
	},
	this._getGoalExpenseList = function(dom, subject){
		if (dom && subject) {
			var dataList = dom.getElementsByTagName(subject),
				resDataList = {};
			if (dataList) {
				for(var i=0; i<dataList.length; i++){
					var dataItem = dataList[i];
					if (resDataList[dataItem.getAttribute('plannedDate')] == undefined) {
						resDataList[dataItem.getAttribute('plannedDate')] = new Array();
					}
					if(subject == 'actualGoalCredit'){
						resDataList[dataItem.getAttribute('plannedDate')].push(this._getGoalExpenseItem(dataItem.childNodes, 'goal'));
					} 
					if (subject == 'actualExpense'){
						resDataList[dataItem.getAttribute('plannedDate')].push(this._getGoalExpenseItem(dataItem.childNodes, 'expense'));
					}
				}
			}
			return resDataList;
		}
		return null;
	},
	/**
	 * Retrieve goal credits.
	 * @param dom the XML response
	 */
	this.getGoalCredits = function(dom){
		return this._getGoalExpenseList(dom, 'actualGoalCredit');
	},
	this.getExpenses = function(dom){
		return this._getGoalExpenseList(dom, 'actualExpense');
	},
	/**
	 * Analyze given XML nodes and return goal credit information.
	 * @param nodes the XML nodes to work with
	 */
	this._getGoalExpenseItem = function(nodes, subject){
		if (nodes && subject) {
			var goal = new Array(), len = nodes.length;
			for ( var i = 0; i < len; i++) {
				// get name
				if (nodes[i].nodeName == subject) {
					goal['name'] = nodes[i].getAttribute('name');
				}
				// get value
				if (nodes[i].nodeName == 'planned' && nodes[i].firstChild) {
					goal['planned'] = nodes[i].firstChild.nodeValue;
				}
			}
			return goal;
		}
		return null;
	},
	/**
	 * Prepare HTML representation of the credit goals.
	 * @param goals the credit goals of a day 
	 */
	this.prepareGoalCreditHtml = function(goals, expenses, creditDate){
		var html = '';
		if (goals) {
			var len = goals.length;
			if (len>0) {
				html += '<strong>'+this.prefs.getMsg('goals')+'</strong>:<br/>';
			}
			for ( var i = 0; i < len; i++) {
				if (i>0) {
					html += '<br/>';
				}
				html += '<span><strong>'+goals[i].planned+' '+this.currency+'</strong> '+goals[i].name+'</span>';
			}
		}
		if (expenses) {
			var len = expenses.length;
			if (len>0) {
				if (html != '') {
					html += '<br/>';
				}
				html += '<strong>'+this.prefs.getMsg('regExpenses')+'</strong>:<br/>';
			}
			for ( var i = 0; i < len; i++) {
				if (i>0) {
					html += '<br/>';
				}
				html += '<span><strong>'+expenses[i].planned+' '+this.currency+'</strong> '+expenses[i].name+'</span>';
			}
		}
		if (html != '') {
			html = '<div id="creditGoal_'+creditDate
				+ '" class="creditGoal hint" style="visibility: hidden; position: absolute; left: 65px; z-index: 5000000; top: 5px; width: 220;">'
				+ '<span style="position: absolute; left: 92%; top: 2px;"><img src="http://4kgadget.googlecode.com/svn/trunk/img/close_btn.gif" style="cursor:pointer; border:none; alt="'+this.prefs.getMsg('close')+'" title="'+this.prefs.getMsg('close')+'" onclick="fourKgadget_toggleCreditGoal(\''+creditDate+'\');"></span>'
				+ html;
			html += '</div>';
		}
		return html;
	},
	/**
	 * Init object.
	 */
	this.init = function(){
		this.baseUrl = this.prefs.getString('baseUrl'+this.mode);
		this.executionUrl = this.baseUrl+this.prefs.getString('executionUrl');
		this.dailyExpenseUrl = this.baseUrl+this.prefs.getString('dailyExpenseUrl');
		//get account data
		this._retriveAccountData();
	},
	this.init()
};
var fkg = new FourKGadget();
// generate envelope content
var fourKgadget_generateEnvelope = function(dom) {
	var personList = dom.getElementsByTagName('person'), 
		html = '', 
		persons = new Array(), 
		goalCredits = fkg.getGoalCredits(dom),
		regExpenses = fkg.getExpenses(dom),
		expenses = new Array();
	html += fkg.getEnvelopeSize(dom);
	html += "<table>";
	// gather header
	html += "<tr><th>" + fourKgadget_prefs.getMsg('date') + "</th>";
	for ( var i = 0; i < personList.length; i++) {
		var personDom = personList.item(i);
		html += '<th colspan="2">' + personDom.getAttribute('name') + "</th>";
	}
	html += "</tr>";
	// gather expenses
	for ( var i = 0; i < personList.length; i++) {
		var personDom = personList.item(i);
		var personId = personDom.getAttribute('id');
		// gather person expenses
		var personExpenses = new Array(), expensesList = personDom.childNodes;
		for ( var ex = 0; ex < expensesList.length; ex++) {
			var pHtml = '', 
				expression = '', 
				sum = '',
				expenseDate = '';
			if (expensesList.item(ex).nodeName != "dailyExpense")
				continue;
			expenseDate = expensesList.item(ex).getAttribute("date");
			// accept date if there is only one person
			if (i == 0) {
				pHtml += '<td><span style="${style}" title="'+fkg.prefs.getMsg('goalsAndExpenses')+'" onclick="fourKgadget_toggleCreditGoal(\''+expenseDate+'\');">' + fourKgadget_createEnvelopeDate(expenseDate)+'</span>';
				if (goalCredits[expenseDate] || regExpenses[expenseDate]) {
					pHtml = pHtml.replace('${style}', 'cursor:pointer; text-decoration: underline;');
					pHtml += fkg.prepareGoalCreditHtml(goalCredits[expenseDate], regExpenses[expenseDate], expenseDate); 
				}
				pHtml += '</td>';
			}
			for ( var exp = 0; exp < expensesList.item(ex).childNodes.length; exp++) {
				if (expensesList.item(ex).childNodes[exp].nodeName == "expression"
						&& expensesList.item(ex).childNodes[exp].firstChild) {
					expression = expensesList.item(ex).childNodes[exp].firstChild.nodeValue;
				}
				if (expensesList.item(ex).childNodes[exp].nodeName == "sum"
						&& expensesList.item(ex).childNodes[exp].firstChild) {
					sum = expensesList.item(ex).childNodes[exp].firstChild.nodeValue;
					if (sum == "0") {
						sum = "-";
					}
				}
			}
			pHtml += '<td align="center">&nbsp;&nbsp;&nbsp;<span id="sumHolder_'
					+ expenseDate
					+ '_'
					+ personId
					+ '">'
					+ sum
					+ '</span></td>';
			pHtml += '<td><img src="http://4kgadget.googlecode.com/svn/trunk/img/edit.jpg" class="ie6pngfix" title="'
					+ fourKgadget_prefs.getMsg('extendedEdit')
					+ '" alt="'
					+ fourKgadget_prefs.getMsg('extendedEdit')
					+ '" onclick="fourKgadget_showExpenseEditor(\''
					+ expenseDate
					+ '_'
					+ personId
					+ '\')" style="cursor:pointer;"/>';
			pHtml += '<span id="exprHolder_' + expenseDate + '_' + personId
					+ '" style="display:none;">' + expression + '</span></td>';
			// store expense
			personExpenses.push(pHtml);
		}
		expenses.push(personExpenses);
	}
	// generate expenses html
	for (d = 0; d <= 6; d++) {
		html += "<tr>";
		for ( var p = 0; p < expenses.length; p++) {
			html += expenses[p][d];
		}
		html += "</tr>";
	}
	// write data
	var contentContainer = document.getElementById('4kgadget_content');
	contentContainer.innerHTML = html + "</table>";
};
var fourKgadget_toggleCreditGoal = function(creditDay){
	if (creditDay) {
		var container = document.getElementById('creditGoal_'+creditDay),
			visibileContainer = document.getElementById('visibleCreditGoalId');
		var visibileContainerId = visibileContainer.innerHTML;
		if(visibileContainerId != '' && visibileContainerId != container.id){
			document.getElementById(visibileContainerId).style.visibility = 'hidden';
		}
		if (container && container.style.visibility == 'visible') {
			container.style.visibility = 'hidden';
		} else {
			container.style.visibility = 'visible';
			container.style.top = container.parentNode.offsetTop+18;
			visibileContainer.innerHTML = container.id;
		}
	}
};
// show expense editor
var fourKgadget_showExpenseEditor = function(expenseContainerId) {
	var editor = document.getElementById('4kgadget_EnvelopeExpressionPopup'), 
		sum = document.getElementById('sumHolder_' + expenseContainerId), 
		exp = document.getElementById('exprHolder_' + expenseContainerId), 
		expenseEditor = document.getElementById('4kgadget_editExpression');
	editor.style.visibility = "visible";
	var value = exp.innerHTML;
	if (value == "-") {
		value = "";
	}
	expenseEditor.value = '';
	expenseEditor.value = value;
	// set active person id
	ACTIVE_EXPENSE = expenseContainerId;
	// recalculate gadget height
	fourKgadget_recalculateOnExpenseChange();
};

// show form to enter credentials
var fourKgadget_doValidateCredentials = function() {
	var fourKgadget_login = fourKgadget_prefs.getString("login"), fourKgadget_password = fourKgadget_prefs
			.getString("password");
	if ((!fourKgadget_login && !fourKgadget_password)
			|| (fourKgadget_login !== "" && fourKgadget_password == "")) {
		var credentialsContainer = document
				.getElementById('4kgadget_credentialsForm');
		credentialsContainer.style.display = "block";
	} else {
		isValidationPassed = true;
	}
};
// persist credentials
var fourKgadget_saveCredentials = function() {
	var login = document.getElementById('fourKgadget_login').value, password = document
			.getElementById('fourKgadget_password').value;
	if(login == "" && password == ""){
		fourKgadget_msg.createTimerMessage(fourKgadget_prefs.getMsg('input_credentials'), 5);
		return;
	}
	fourKgadget_prefs.set('login', login);
	fourKgadget_prefs.set('password', password);
	var message = fourKgadget_msg
			.createTimerMessage(
					fourKgadget_prefs.getMsg('credentialsSaved'),
					2,
					function() {
						// hide credentials form
						var credentialsContainer = document
								.getElementById('4kgadget_credentialsForm').style.display = "none";
						// load data
						fourKgadget_envelopeDataLoader();
						// hide message
						fourKgadget_msg.dismissMessage(message);
					});
};
// visibility handler
var fourKgadget_toggleVisibility = function() {
	var helpContainer = document
			.getElementById('4kgadget_moreExpressionSamples');
	var state = helpContainer.style.display;
	if (state == 'none') {
		helpContainer.style.display = 'block';
	} else {
		helpContainer.style.display = 'none';
	}
};
// save expense handler
var fourKgadget_saveExpenseHandler = function() {
	// hide expression edit dialog
	fourKgadget_cancelExpenseHandler();
	var expression = document.getElementById('4kgadget_editExpression').value, expenseData = ACTIVE_EXPENSE
			.split('_'), localDailyExpenseUrl = '';
	localDailyExpenseUrl += dailyExpenseUrl
			+ fourKgadget_prefs.getString('login')
			+ fourKgadget_prefs.getString('dailyExpenseUrl') + expenseData[1]
			+ '/' + expenseData[0];
	localDailyExpenseUrl += '?expression=' + encodeURI(expression);
	fourKgadget_RequestHandler(
			localDailyExpenseUrl,
			fourKgadget_prefs.getMsg('expenseSaving'),
			function(obj) {
				var domdata = obj.data;
				if (domdata) {
					var expense = domdata.getElementsByTagName("dailyExpense")
							.item(0), sum = 0, expression = '', sum = document
							.getElementById('sumHolder_' + ACTIVE_EXPENSE), exp = document
							.getElementById('exprHolder_' + ACTIVE_EXPENSE);
					for ( var i = 0; i < expense.childNodes.length; i++) {
						if (expense.childNodes[i].nodeName == 'expression'
								&& expense.childNodes[i].firstChild) {
							exp.innerHTML = expense.childNodes[i].firstChild.nodeValue
						}
						if (expense.childNodes[i].nodeName == 'sum'
								&& expense.childNodes[i].firstChild) {
							sum.innerHTML = expense.childNodes[i].firstChild.nodeValue
						}
					}
					// hide message
					fourKgadget_msg.dismissMessage(statusMessage);
				} else {
					fourKgadget_msg.createTimerMessage(fourKgadget_prefs
							.getMsg('expenseSaveFailed'), 4);
				}
			}, gadgets.io.MethodType.POST);
	// track usage
	fourKgadget_trackUsage("Save Expense");
};
// function to perform remote requests
var fourKgadget_RequestHandler = function(url, message, callback, method) {
	// request application data
	var params = {}, headers = {};
	if (method == undefined) {
		method = gadgets.io.MethodType.GET;
	}
	params[gadgets.io.RequestParameters.METHOD] = method;
	params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
	headers['4KAuth'] = fourKgadget_prefs.getString('password');
	headers['4KApplication'] = fourKgadget_prefs.getString('apiKey');
	params[gadgets.io.RequestParameters.HEADERS] = headers;
	if (callback == undefined) {
		callback = function() {
		};
	}
	gadgets.io.makeRequest(url, callback, params);
	statusMessage = fourKgadget_msg
			.createStaticMessage("<span class='message'>" + message + "</span>");
};
// cancle button on expense expression handler
var fourKgadget_cancelExpenseHandler = function() {
	var editor = document.getElementById('4kgadget_EnvelopeExpressionPopup');
	editor.style.visibility = "hidden";
	// recalculate gadget height
	fourKgadget_recalculateOnExpenseChange();
};
var isHeighEncreased = false;
// recalculate gadget size on expense input
var fourKgadget_recalculateOnExpenseChange = function() {
	var currHeight = gadgets.window.getViewportDimensions().height;
	if (currHeight < 250) {
		gadgets.window.adjustHeight(currHeight + 30);
		isHeighEncreased = true;
	}
	if (currHeight > 250 && isHeighEncreased) {
		gadgets.window.adjustHeight(currHeight - 30);
	}
};
// reset credentials
var fourKgadget_resetCredentials = function() {
	// reset credentials
	fourKgadget_prefs.set('login', '');
	fourKgadget_prefs.set('password', '');
	// hide content view
	var contentContainer = document.getElementById('4kgadget_content'), credentialsContainer = document
			.getElementById('4kgadget_credentialsForm');
	contentContainer.style.display = "none";
	// show enter credentials form
	if (credentialsContainer.style.display == "none") {
		credentialsContainer.style.display = "block";
	}
	var login = document.getElementById('fourKgadget_login').value = '', password = document
			.getElementById('fourKgadget_password').value = '';
	gadgets.window.adjustHeight(250);
};
// register credentials validation handler
gadgets.util.registerOnLoadHandler(fourKgadget_startApplication);